"""
双均线交叉策略
当快线上穿慢线时买入，下穿时卖出
"""
import pandas as pd
import numpy as np
from typing import Dict
from strategies.base_strategy import BaseStrategy


class MACrossStrategy(BaseStrategy):
    """双均线交叉策略"""
    
    def __init__(self, config: Dict):
        """
        初始化双均线策略
        
        参数:
            config: 策略配置
        """
        super().__init__(config)
        
        # 策略特定参数
        self.fast_period = self.params.get('fast_period', 10)
        self.slow_period = self.params.get('slow_period', 20)
        self.timeframe = self.params.get('timeframe', '15m')
        self.ma_type = self.params.get('ma_type', 'EMA')
        
        # 验证参数
        if self.fast_period >= self.slow_period:
            raise ValueError(f"快线周期({self.fast_period})必须小于慢线周期({self.slow_period})")
        
        print(f"双均线策略初始化: 快线={self.fast_period}, 慢线={self.slow_period}, 类型={self.ma_type}")
    
    def calculate_ma(self, data: pd.Series, period: int) -> pd.Series:
        """
        计算移动平均线
        
        参数:
            data: 价格数据
            period: 周期
            
        返回:
            移动平均线序列
        """
        if self.ma_type == 'SMA':
            return data.rolling(window=period).mean()
        elif self.ma_type == 'EMA':
            return data.ewm(span=period, adjust=False).mean()
        elif self.ma_type == 'WMA':
            weights = np.arange(1, period + 1)
            return data.rolling(window=period).apply(
                lambda x: np.dot(x, weights) / weights.sum(), raw=True
            )
        else:
            raise ValueError(f"不支持的均线类型: {self.ma_type}")
    
    def generate_signal(self, symbol: str, market_data: pd.DataFrame) -> Dict:
        """
        生成交易信号
        
        参数:
            symbol: 交易对
            market_data: 市场数据，包含列：timestamp, open, high, low, close, volume
            
        返回:
            信号字典
        """
        # 检查数据长度
        if len(market_data) < self.slow_period + 1:
            return {
                'action': 'hold',
                'confidence': 0.0,
                'reason': f'数据不足，需要至少{self.slow_period + 1}根K线'
            }
        
        # 计算快慢均线
        close_prices = market_data['close']
        fast_ma = self.calculate_ma(close_prices, self.fast_period)
        slow_ma = self.calculate_ma(close_prices, self.slow_period)
        
        # 获取最近的均线值
        current_fast = fast_ma.iloc[-1]
        current_slow = slow_ma.iloc[-1]
        prev_fast = fast_ma.iloc[-2]
        prev_slow = slow_ma.iloc[-2]
        
        # 检查是否有效
        if pd.isna(current_fast) or pd.isna(current_slow):
            return {
                'action': 'hold',
                'confidence': 0.0,
                'reason': '均线计算结果无效'
            }
        
        # 判断交叉
        current_price = close_prices.iloc[-1]
        
        # 金叉：快线上穿慢线（买入信号）
        if prev_fast <= prev_slow and current_fast > current_slow:
            # 计算信号强度
            cross_strength = abs(current_fast - current_slow) / current_slow
            confidence = min(0.5 + cross_strength * 10, 1.0)  # 0.5-1.0
            
            return {
                'action': 'buy',
                'confidence': confidence,
                'reason': f'金叉信号: 快线({current_fast:.2f})上穿慢线({current_slow:.2f})',
                'price': current_price,
                'fast_ma': current_fast,
                'slow_ma': current_slow
            }
        
        # 死叉：快线下穿慢线（卖出信号）
        elif prev_fast >= prev_slow and current_fast < current_slow:
            cross_strength = abs(current_fast - current_slow) / current_slow
            confidence = min(0.5 + cross_strength * 10, 1.0)
            
            return {
                'action': 'sell',
                'confidence': confidence,
                'reason': f'死叉信号: 快线({current_fast:.2f})下穿慢线({current_slow:.2f})',
                'price': current_price,
                'fast_ma': current_fast,
                'slow_ma': current_slow
            }
        
        # 持仓中，检查是否需要平仓
        elif symbol in self.positions:
            position = self.positions[symbol]
            
            # 多头持仓，快线下穿慢线时平仓
            if position['side'] == 'long' and current_fast < current_slow:
                return {
                    'action': 'close',
                    'confidence': 0.8,
                    'reason': f'多头平仓: 快线({current_fast:.2f})低于慢线({current_slow:.2f})',
                    'price': current_price
                }
            
            # 空头持仓，快线上穿慢线时平仓
            elif position['side'] == 'short' and current_fast > current_slow:
                return {
                    'action': 'close',
                    'confidence': 0.8,
                    'reason': f'空头平仓: 快线({current_fast:.2f})高于慢线({current_slow:.2f})',
                    'price': current_price
                }
        
        # 无信号
        return {
            'action': 'hold',
            'confidence': 0.0,
            'reason': f'无交叉信号: 快线={current_fast:.2f}, 慢线={current_slow:.2f}',
            'fast_ma': current_fast,
            'slow_ma': current_slow
        }
    
    def calculate_position_size(self, symbol: str, signal: Dict, account_balance: float) -> float:
        """
        计算开仓数量
        
        参数:
            symbol: 交易对
            signal: 交易信号
            account_balance: 账户余额
            
        返回:
            开仓数量（USDT价值）
        """
        # 基础仓位大小
        base_size = account_balance * self.position_size
        
        # 根据信号置信度调整
        confidence = signal.get('confidence', 0.5)
        adjusted_size = base_size * confidence
        
        # 应用杠杆
        leveraged_size = adjusted_size * self.leverage
        
        # 确保不超过最大仓位限制
        max_position = account_balance * 0.3  # 单策略最大30%
        final_size = min(leveraged_size, max_position)
        
        return final_size
    
    def get_required_history(self) -> int:
        """
        获取所需的历史数据长度
        
        返回:
            所需K线数量
        """
        return self.slow_period + 10  # 多留一些数据以确保计算准确


if __name__ == "__main__":
    # 测试策略
    config = {
        'name': '双均线测试',
        'enabled': True,
        'category': 'trend',
        'params': {
            'fast_period': 10,
            'slow_period': 20,
            'timeframe': '15m',
            'ma_type': 'EMA'
        },
        'trading': {
            'symbols': ['BTC-USDT-SWAP'],
            'leverage': 3,
            'position_size': 0.1
        },
        'risk': {
            'stop_loss': 0.02,
            'take_profit': 0.04,
            'trailing_stop': True
        }
    }
    
    # 创建策略实例
    strategy = MACrossStrategy(config)
    
    # 生成模拟数据
    dates = pd.date_range(start='2024-01-01', periods=100, freq='15min')
    np.random.seed(42)
    prices = 50000 + np.cumsum(np.random.randn(100) * 100)
    
    market_data = pd.DataFrame({
        'timestamp': dates,
        'open': prices,
        'high': prices + np.random.rand(100) * 50,
        'low': prices - np.random.rand(100) * 50,
        'close': prices,
        'volume': np.random.rand(100) * 1000
    })
    
    # 生成信号
    signal = strategy.generate_signal('BTC-USDT-SWAP', market_data)
    print(f"\n信号: {signal}")
    
    # 计算仓位
    if signal['action'] in ['buy', 'sell']:
        position_size = strategy.calculate_position_size('BTC-USDT-SWAP', signal, 10000)
        print(f"建议仓位: {position_size:.2f} USDT")
    
    # 显示性能指标
    print(f"\n策略信息: {strategy}")
    print(f"性能指标: {strategy.get_performance_metrics()}")
